//
//  UIPhotoView.m
//  storeapp
//
//  Created by huangyi on 13-3-15.
//  Copyright (c) 2013年 ios. All rights reserved.
//

#import "UIPhotoView.h"
#import <QuartzCore/QuartzCore.h>
#import "UIView+utils.h"
#import "UIImage+utils.h"
#import "UIImageView+utils.h"
#import "NSString+path.h"

@interface UIDrawView : UIView

@property(nonatomic,strong)UIColor *penColor;
@property(nonatomic)int penSize;
@property(nonatomic,strong)UIImage *image;
@property(nonatomic,assign)NSMutableArray *penPoint;

@end

@implementation UIDrawView

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        self.backgroundColor=[UIColor clearColor];
    }
    return self;
}

-(void)drawRect:(CGRect)rect{
    [self.image drawAtPoint:CGPointZero];
    CGContextRef ctx=UIGraphicsGetCurrentContext();
    CGContextSetStrokeColorWithColor(ctx, self.penColor.CGColor);
    CGContextSetLineCap(ctx, kCGLineCapRound);
    CGContextSetLineWidth(ctx, self.penSize);
    if (self.penPoint.count) {
        int count=self.penPoint.count;
        for (int i=0; i<count; i++) {
            CGPoint pt=CGPointFromString(self.penPoint[i]);
            if (i==0) {
                CGContextMoveToPoint(ctx, pt.x, pt.y);
            }else{
                CGContextAddLineToPoint(ctx, pt.x, pt.y);
            }
        }
        CGContextDrawPath(ctx, kCGPathStroke);
    }
}

@end

@interface UIPhotoView () <UIGestureRecognizerDelegate>

@property(nonatomic,assign)id responder;
@property(nonatomic)SEL selector;

@property(nonatomic,assign)UIImageView *photo;
@property(nonatomic,assign)UIDrawView *canvas;
@property(nonatomic,assign)UIView *overlay;

@property(nonatomic,strong)UIColor *penColor;
@property(nonatomic)CGFloat penSize;
@property(nonatomic,strong)NSMutableArray *penPoint;

@end

@implementation UIPhotoView

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        [self initView];
    }
    return self;
}
-(id)initWithCoder:(NSCoder *)aDecoder{
    self=[super initWithCoder:aDecoder];
    if (self) {
        [self initView];
    }
    return self;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    // Drawing code
}
*/
-(void)initView{
    self.clipsToBounds=YES;
    UIImageView *p=[[UIImageView alloc] initWithFrame:self.frame];
    [self addSubview:p];
    self.photo=p;
    UIView *l=[[UIView alloc] initWithFrame:self.frame];
    [self addSubview:l];
    self.overlay=l;
    UIDrawView *c=[[UIDrawView alloc] initWithFrame:self.frame];
    [self addSubview:c];
    self.canvas=c;

    UIPinchGestureRecognizer *pinch=[[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(didPinch:)];
    [self addGestureRecognizer:pinch];
    pinch.delegate=self;
    UIPanGestureRecognizer *pan=[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(didPan:)];
    [self addGestureRecognizer:pan];
    pan.delegate=self;
    UIRotationGestureRecognizer *rot=[[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(didRotate:)];
    [self addGestureRecognizer:rot];
    rot.delegate=self;
    UITapGestureRecognizer *singleTap=[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didSingleTap:)];
    [self addGestureRecognizer:singleTap];
    singleTap.delegate=self;
    singleTap.numberOfTapsRequired=1;
    UITapGestureRecognizer *doubleTap=[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didDoubleTap:)];
    [self addGestureRecognizer:doubleTap];
    doubleTap.delegate=self;
    doubleTap.numberOfTapsRequired=2;
    
    [singleTap requireGestureRecognizerToFail:doubleTap];

    [self setImage:nil];
    self.allowMoveAndScale=NO;
    self.allowRotate=NO;
    [self viewPhoto:YES];
}

-(void)didPinch:(UIPinchGestureRecognizer*)pinch{
    if (self.photo.userInteractionEnabled && self.allowMoveAndScale) {
        static float scale;
        static float translateX;
        static float translateY;
        static CGPoint offset;
        if (pinch.state==UIGestureRecognizerStateBegan) {
            scale=self.scale;
            translateX=self.translateX;
            translateY=self.translateY;
            offset=[pinch locationInView:self];
            CGPoint pivot=CGPointMake(CGRectGetMidX(self.photo.frame), CGRectGetMidY(self.photo.frame));
            offset=CGPointMake(pivot.x-offset.x, pivot.y-offset.y);
        }
        if (pinch.state==UIGestureRecognizerStateChanged) {
            self.scale=scale*pinch.scale;
            self.translateX=translateX+offset.x*(pinch.scale-1);
            self.translateY=translateY+offset.y*(pinch.scale-1);
            [self calculateTransform];
        }
        if (pinch.state==UIGestureRecognizerStateEnded) {
            [self calculateImageRect];
        }
    }
}
-(void)didPan:(UIPanGestureRecognizer*)pan{
    if (self.photo.userInteractionEnabled && self.allowMoveAndScale) {
        static float translateX;
        static float translateY;
        if (pan.state==UIGestureRecognizerStateBegan) {
            translateX=self.translateX;
            translateY=self.translateY;
        }
        if (pan.state==UIGestureRecognizerStateChanged) {
            CGPoint translate=[pan translationInView:self];
            self.translateX=translateX+translate.x;
            self.translateY=translateY+translate.y;
            [self calculateTransform];
        }
        if (pan.state==UIGestureRecognizerStateEnded) {
            [self calculateImageRect];
        }
    }
}
-(void)didRotate:(UIRotationGestureRecognizer*)rot{
    if (self.photo.userInteractionEnabled && self.allowRotate) {
        static float rotate;
        if (rot.state==UIGestureRecognizerStateBegan) {
            rotate=self.rotate;
        }
        if (rot.state==UIGestureRecognizerStateChanged) {
            self.rotate=rotate+rot.rotation;
            [self calculateTransform];
        }
        if (rot.state==UIGestureRecognizerStateEnded) {
            [self calculateImageRect];
        }
    }
}
-(void)didSingleTap:(UITapGestureRecognizer*)tap{
    if (self.photo.userInteractionEnabled) {
        CGPoint p=[tap locationInView:self.overlay];
        UIView *v=nil;
        for (UIView *s in self.overlay.subviews) {
            if (CGRectContainsPoint(s.frame, p)) {
                v=s;
            }
        }
        if (v) {
            [self.overlay bringSubviewToFront:v];
        }else{
            v=self;
        }
        if ([self.responder respondsToSelector:self.selector]) {
            [self.responder performSelector:self.selector withObject:v afterDelay:0];
        }
    }
}
-(void)didDoubleTap:(UITapGestureRecognizer*)tap{
    if (self.photo.userInteractionEnabled && self.allowMoveAndScale) {
        [UIView animateWithDuration:0.2 animations:^{
            float a=ABS(1-self.scale);
            if (a<0.01) {
                [self initTransform];
            }else{
                self.translateX=0;
                self.translateY=0;
                self.rotate=0;
                self.scale=1;
                [self calculateTransform];
            }
        }];
    }
}
-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
    if (!self.photo.userInteractionEnabled) {
        return NO;
    }
    if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) {
        UITapGestureRecognizer *tap=(id)gestureRecognizer;
        if (tap.numberOfTapsRequired==1) {
            return YES;
        }
    }
    if ([gestureRecognizer isKindOfClass:[UIRotationGestureRecognizer class]]) {
        if (!self.allowRotate) {
            return NO;
        }
    }
    if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) {
        if (CGRectContainsRect(self.bounds, self.photo.frame)) {
            if (gestureRecognizer.delegate==self) {
                return NO;
            }
        }
    }
    return self.allowMoveAndScale;
}

-(void)addTarget:(id)target action:(SEL)action{
    self.responder=target;
    self.selector=action;
}

-(UIImage*)image{
    return self.photo.image;
}
-(void)setImage:(UIImage*)image{
    if (image) {
        self.photo.image=image;
    }else{
        self.photo.image=[UIImage imageWithSize:self.frame.size];
    }
    [self.photo sizeToFit];
    self.photo.center=self.cp;
    self.canvas.frame=self.photo.frame;
    self.overlay.frame=self.photo.frame;
    self.isOverlayHidden=NO;
    [self initTransform];
}
-(void)setImageFromURL:(NSString*)urlstr{
    [self.photo imageFromURL:urlstr diskCache:YES onComplete:^{
        [self setImage:self.photo.image];
    }];
}

-(void)initTransform{
    float scale=1;
    CGSize imageSize=self.photo.image.size;
    if (!CGSizeEqualToSize(imageSize, CGSizeZero)) {
        switch (self.contentMode) {
            case UIViewContentModeScaleAspectFill:
                scale=MAX(CGRectGetWidth(self.bounds)/imageSize.width, CGRectGetHeight(self.bounds)/imageSize.height);
                break;
            default:
                scale=MIN(CGRectGetWidth(self.bounds)/imageSize.width, CGRectGetHeight(self.bounds)/imageSize.height);
                break;
        }
    }
    self.translateX=0;
    self.translateY=0;
    self.rotate=0;
    self.scale=MIN(1, scale);
    [self calculateTransform];
}

-(void)calculateTransform{
    CGAffineTransform transform=CGAffineTransformIdentity;
    transform=CGAffineTransformTranslate(transform, self.translateX, self.translateY);
    transform=CGAffineTransformScale(transform, self.scale, self.scale);
    transform=CGAffineTransformRotate(transform, self.rotate);
    self.photo.transform=transform;
    self.canvas.transform=transform;
    self.overlay.transform=transform;
}

-(void)calculateImageRect{
    CGRect rect=self.photo.frame;
    if (CGRectGetWidth(rect)<CGRectGetWidth(self.bounds)) {
        self.translateX=0;
    }else{
        float left=CGRectGetMinX(rect);
        if (left>0) {
            self.translateX-=left;
        }
        float right=CGRectGetWidth(self.bounds)-CGRectGetMaxX(rect);
        if (right>0) {
            self.translateX+=right;
        }
    }
    if (CGRectGetHeight(rect)<CGRectGetHeight(self.bounds)) {
        self.translateY=0;
    }else{
        float up=CGRectGetMinY(rect);
        if (up>0) {
            self.translateY-=up;
        }
        float down=CGRectGetHeight(self.bounds)-CGRectGetMaxY(rect);
        if (down>0) {
            self.translateY+=down;
        }
    }
    [UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
        [self calculateTransform];
    } completion:nil];
}

-(void)setOverlayWithViews:(NSArray*)array{
    [self.overlay removeAllSubviews];
    int count=array.count;
    for (int i=0; i<count; i++) {
        UIView *v=array[i];
        v.userInteractionEnabled=YES;
        v.tag=i;
        [self.overlay addSubview:v];
    }
}
-(void)addOverlayWithView:(UIView*)view{
    int count=self.overlay.subviews.count;
    view.userInteractionEnabled=YES;
    view.tag=count;
    [self.overlay addSubview:view];
    view.center=CGPointMake(CGRectGetMidX(self.overlay.bounds), CGRectGetMidY(self.overlay.bounds));
}

-(void)viewPhoto:(BOOL)enable{
    self.photo.userInteractionEnabled=enable;
    self.canvas.userInteractionEnabled=NO;
    self.overlay.userInteractionEnabled=NO;
}

-(void)drawWithSize:(CGFloat)penSize andColor:(UIColor*)penColor{
    self.photo.userInteractionEnabled=NO;
    self.canvas.userInteractionEnabled=YES;
    self.overlay.userInteractionEnabled=NO;
    if (penSize==0) {
        penSize=6;
    }
    self.penSize=penSize;
    if (penColor==nil) {
        penColor=[UIColor redColor];
    }
    self.penColor=penColor;
    self.canvas.penColor=penColor;
    self.canvas.penSize=penSize;
}
-(void)clearCanvas{
    self.canvas.image=nil;
}

-(void)layoutOverlay:(BOOL)editing{
    self.photo.userInteractionEnabled=NO;
    self.canvas.userInteractionEnabled=NO;
    self.overlay.userInteractionEnabled=editing;
}
-(void)showOverlay:(BOOL)hidden{
    self.isOverlayHidden=hidden;
    self.overlay.hidden=hidden;
}

-(UIImage*)renderToImage{
    float tx=self.translateX;
    float ty=self.translateY;
    float r=self.rotate;
    float s=self.scale;

    self.translateX=0;
    self.translateY=0;
    self.rotate=0;
    self.scale=1;
    [self calculateTransform];

    CGRect rect=CGRectMake(0, 0, self.photo.image.size.width, self.photo.image.size.height);
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef ctx=UIGraphicsGetCurrentContext();
    CGContextScaleCTM(ctx,1.0f,1.0f);
    [[self.photo imageFromView] drawInRect:rect];
    [[self.canvas imageFromView] drawInRect:rect];
    [[self.overlay imageFromView] drawInRect:rect];
    UIImage* snapshot=UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    self.translateX=tx;
    self.translateY=ty;
    self.rotate=r;
    self.scale=s;
    [self calculateTransform];

    return snapshot;
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    if (self.overlay.userInteractionEnabled) {
        UITouch *touch=touches.anyObject;
        UIView *v=touch.view;
        [self.overlay bringSubviewToFront:v];
        return;
    }
    if (self.canvas.userInteractionEnabled) {
        UITouch *touch=touches.anyObject;
        CGPoint p=[touch locationInView:self.canvas];
        self.penPoint=[NSMutableArray array];
        self.canvas.penPoint=self.penPoint;
        [self.penPoint addObject:NSStringFromCGPoint(p)];
        return;
    }
    [super touchesBegan:touches withEvent:event];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    if (self.canvas.userInteractionEnabled) {
        UITouch *touch=touches.anyObject;
        CGPoint p1=[touch previousLocationInView:self.canvas];
        CGPoint p2=[touch locationInView:self.canvas];
        [self.penPoint addObject:NSStringFromCGPoint(p2)];
        float minX=MIN(p1.x, p2.x);
        float maxX=MAX(p1.x, p2.x);
        float minY=MIN(p1.y, p2.y);
        float maxY=MAX(p1.y, p2.y);
        [self.canvas setNeedsDisplayInRect:CGRectMake(minX-10, minY-10, (maxX-minX)+10, (maxY-minY)+10)];
        return;
    }
    if (self.overlay.userInteractionEnabled) {
        UITouch *touch=touches.anyObject;
        CGPoint p1=[touch previousLocationInView:self.canvas];
        CGPoint p2=[touch locationInView:self.canvas];
        UIView *v=nil;
        for (UIView *s in self.overlay.subviews) {
            if (CGRectContainsPoint(s.frame, p1)) {
                v=s;
            }
        }
        if (v!=nil) {
            CGRect prev=v.frame;
            v.frame=CGRectOffset(v.frame, p2.x-p1.x, p2.y-p1.y);
            if (!CGRectContainsPoint(self.overlay.bounds, v.center)) {
                v.frame=prev;
            }
        }
        return;
    }
    [super touchesMoved:touches withEvent:event];
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    if (self.canvas.userInteractionEnabled) {
        UITouch *touch=touches.anyObject;
        CGPoint p=[touch locationInView:self.canvas];
        [self.penPoint addObject:NSStringFromCGPoint(p)];
        [self.canvas setNeedsDisplay];
        [self updateCanvas];
        return;
    }
    [super touchesEnded:touches withEvent:event];
}
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event{
    [self touchesEnded:touches withEvent:event];
}

-(void)updateCanvas{
    self.canvas.image=[self.canvas imageFromView];
    self.penPoint=nil;
    self.canvas.penPoint=nil;
}
-(NSArray*)dumpOverlayInfo{
    NSMutableArray *array=[NSMutableArray array];
    for (UIView *o in self.overlay.subviews) {
        [array addObject:o];
    }
    return array;
}

@end
